package com.example.other.netty.endecode;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;

public class PacketCodec {
    public static int MAGIC_NUMBER = 0x12345678;//后端识别首位是这个才进行解析，否则不解析

    public static ByteBuf encode(Packet packet){
        //1、创建byteBuf对象
        ByteBuf byteBuf = ByteBufAllocator.DEFAULT.ioBuffer();

        //2、序列化Java对象
        byte[] bytes = Serializer.DEFAULT.serialize(packet);

        //3、实际编码过程 byte拼接的过程
        //通信协议涉及如下：
        // 魔数 | 版本号 | 序列化算法 | 指令 | 数据长度 | 数据
        //  4      1        1         1       4      N    单位：字节

        byteBuf.writeInt(MAGIC_NUMBER);
        byteBuf.writeByte(packet.getVersion());
        byteBuf.writeByte(Serializer.DEFAULT.getSerializerAlgorithm());
        byteBuf.writeByte(packet.getCommand());
        byteBuf.writeInt(bytes.length);
        byteBuf.writeBytes(bytes);
        return byteBuf;
    }

    public static ByteBuf encode(ByteBuf byteBuf, Packet packet){
        //2、序列化Java对象
        byte[] bytes = Serializer.DEFAULT.serialize(packet);

        //3、实际编码过程 byte拼接的过程
        //通信协议涉及如下：
        // 魔数 | 版本号 | 序列化算法 | 指令 | 数据长度 | 数据
        //  4      1        1         1       4      N    单位：字节

        byteBuf.writeInt(MAGIC_NUMBER);
        byteBuf.writeByte(packet.getVersion());
        byteBuf.writeByte(Serializer.DEFAULT.getSerializerAlgorithm());
        byteBuf.writeByte(packet.getCommand());
        byteBuf.writeInt(bytes.length);
        byteBuf.writeBytes(bytes);
        return byteBuf;
    }

    public static Packet decode(ByteBuf byteBuf) {
        byteBuf.skipBytes(4);

        byteBuf.skipBytes(1);

        byte serializeAlgorithm = byteBuf.readByte();

        byte command = byteBuf.readByte();//指令 根据指令返回packet

        int length = byteBuf.readInt();

        byte[] bytes = new byte[length];
        byteBuf.readBytes(bytes);

        Class<? extends Packet> requestType = getRequestType(command);//获取指令
        Serializer serializer = getSerializer(serializeAlgorithm);//获取序列化方式

        if(requestType != null && serializer != null){
            return serializer.deserialize(requestType, bytes);
        }

        return null;
    }

    private static Serializer getSerializer(byte serializeAlgorithm) {
        if(serializeAlgorithm == SerializerAlgorithm.JSON){
            return new JSONSerializer();
        }
        return null;
    }

    private static Class<? extends Packet> getRequestType(byte command) {
        if(command == Command.LOGIN_REQUEST){
            return new LoginRequestPacket().getClass();
        }else if(command == Command.LOGIN_RESPONSE){
            return new LoginResponsePacket().getClass();
        }else if(command == Command.MESSAGE_RESPONSE){
            return new MessageResponsePacket().getClass();
        }else if(command == Command.MESSAGE_REQUEST){
            return new MessageRequestPacket().getClass();
        }

        return null;
    }
}
